﻿namespace BathroomLocator.Services.Infrastructure
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using BathroomLocator.Services.Models;
	using Microsoft.WindowsAzure;
	using Microsoft.WindowsAzure.StorageClient;

	public class PushUserEndpointContext : TableServiceContext, IPushUserEndpointsRepository
	{
		public const string PushUserTableName = "PushUserEndpoints";

		public PushUserEndpointContext()
			: this(CloudStorageAccount.FromConfigurationSetting("DataConnectionString"))
		{
		}

		public PushUserEndpointContext(CloudStorageAccount account)
			: this(account.TableEndpoint.ToString(), account.Credentials)
		{
		}

		public PushUserEndpointContext(string baseAddress, StorageCredentials credentials)
			: base(baseAddress, credentials)
		{
			this.IgnoreResourceNotFoundException = true;
			this.IgnoreMissingProperties = true;
		}

		public IQueryable<PushUserEndpoint> PushUserEndpoints
		{
			get
			{
				return this.CreateQuery<PushUserEndpoint>(PushUserTableName);
			}
		}

		public void AddUserEndpoint(string userName, Uri channelUri)
		{
			this.AddObject(PushUserTableName, new PushUserEndpoint { UserName = userName, ChannelUri = channelUri.ToString(), TileCount = 0 });

			this.SaveChanges();
		}

		public void RemoveUserEndpoint(string userName, Uri channelUri)
		{
			var pushUserEnpoints = this.GetUsersByNameAndEndpoint(userName, channelUri);
			foreach (var pushUserEnpoint in pushUserEnpoints)
			{
				this.DeleteObject(pushUserEnpoint);
			}

			this.SaveChanges();
		}

		public IEnumerable<string> GetAllUsers()
		{
			return this.PushUserEndpoints
				.ToList()
				.GroupBy(u => u.UserName)
				.Select(g => g.Key);
		}

		public IEnumerable<PushUserEndpoint> GetUsersByName(string userName)
		{
			return this.PushUserEndpoints
				.Where(u => u.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase))
				.AsEnumerable();
		}

		public IEnumerable<PushUserEndpoint> GetUsersByNameAndEndpoint(string userName, Uri channelUri)
		{
			return this.PushUserEndpoints
				.Where(u => u.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) && u.ChannelUri.Equals(channelUri.ToString(), StringComparison.OrdinalIgnoreCase))
				.AsEnumerable();
		}

		public void UpdateUserEndpoint(PushUserEndpoint pushUserEndpoint)
		{
			this.UpdateObject(pushUserEndpoint);

			this.SaveChanges();
		}
	}
}